/*
 * DevicesIIC.c
 *
 *      Author: Honrun
 */
#include "ch32x035.h"
#include "stdio.h"
#include "DevicesDelay.h"
#include "DevicesIIC.h"


#define IIC_SPEED_VALUE     100000
#define IIC_DELAY_TIME      ((1000000.0f / IIC_SPEED_VALUE) + 1.0f)


void vIIC1DmaInit(void)
{
    DMA_InitTypeDef DMA_InitStructure = {0};

    /* enable DMAx */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    /* deinitialize DMA channelx(I2C tx) */
    DMA_DeInit(DMA1_Channel6);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&I2C1->DATAR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)NULL;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = 0;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel6, &DMA_InitStructure);

    DMA_Cmd(DMA1_Channel6, ENABLE);

    /* deinitialize DMA channelx(I2C rx) */
    DMA_DeInit(DMA1_Channel7);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&I2C1->DATAR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)NULL;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = 0;
    DMA_Init(DMA1_Channel7, &DMA_InitStructure);

    DMA_Cmd(DMA1_Channel7, ENABLE);

    /* enable I2CX DMA */
    I2C_DMACmd( I2C1, ENABLE );
}

void vIIC1Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    I2C_InitTypeDef I2C_InitTSturcture = {0};

    /* enable GPIOB clock */
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
    /* enable I2C0 clock */
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );

    /* GPIO重映射到PC18、PC19，具体对应关系请查阅用户手册 */
    GPIO_PinRemapConfig(GPIO_PartialRemap3_I2C1, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_18;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_19;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    I2C_DeInit( I2C1 );
    I2C_InitTSturcture.I2C_ClockSpeed = IIC_SPEED_VALUE;
    I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
    I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_16_9;
    I2C_InitTSturcture.I2C_OwnAddress1 = 0;
    I2C_InitTSturcture.I2C_Ack = ENABLE;
    I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init( I2C1, &I2C_InitTSturcture );

    vIIC1DmaInit();

    /* enable I2C0 */
	I2C_Cmd( I2C1, ENABLE );
}

/*!
    \brief      reset i2c bus
    \param[in]  none
    \param[out] none
    \retval     none
*/
void vIIC1DeInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure={0};
    int8_t i = 0;

    GPIO_SetBits(GPIOA, GPIO_Pin_10);
    GPIO_SetBits(GPIOA, GPIO_Pin_11);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    vDelayUs(100);

    /* 发送9个时钟脉冲，以解除死锁 */
    for(i = 0; i < 9; ++i)
    {
        vDelayUs(5);
        GPIO_ResetBits(GPIOA, GPIO_Pin_10);
        vDelayUs(5);
        GPIO_ResetBits(GPIOA, GPIO_Pin_11);
        vDelayUs(5);
        GPIO_SetBits(GPIOA, GPIO_Pin_10);
        vDelayUs(5);
        GPIO_SetBits(GPIOA, GPIO_Pin_11);
    }

    vIIC1Init();
}

int8_t cI2CxWriteDatas(I2C_TypeDef *I2Cx, uint16_t usIDAddr, uint16_t usRegAddr, void* pvDatas, int32_t iLength)
{
    void (*vI2CxBusReset)(void) = vIIC1DeInit;
    uint8_t *pucDatas = pvDatas;
    uint32_t timeout = 0, startCnt = 0;

    if((iLength < 1) || (pvDatas == NULL))
        return -1;

    /* i2c master sends start signal only when the bus is idle */
    for(timeout = 0; (timeout <= I2C_BUSY_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) != RESET); ++timeout)
    {
        if(timeout >= I2C_BUSY_TIME_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X busy.\r\n", I2Cx);
            return -2;
        }

        vDelayUs(IIC_DELAY_TIME);
    }

    /* 重试 N 次 */
    for(startCnt = 0; startCnt <= I2C_START_OUT; ++startCnt)
    {
        if(startCnt >= I2C_START_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X start out.\r\n", I2Cx);
            return -3;
        }

        I2C_GenerateSTART(I2Cx, ENABLE);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        /* send driver address */
        I2C_Send7bitAddress(I2Cx, usIDAddr, I2C_Direction_Transmitter);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        if(timeout < I2C_BYTE_WRITE_TIME_OUT)
            break;

        vDelayUs(100.0f);
    }

    /* 执行后续操作前，必须清除此状态位 */
    I2C_ClearFlag(I2Cx, I2C_FLAG_ADDR);

    /* send reg address */
    I2C_SendData(I2Cx, usRegAddr);

    while((iLength--) > 0)
    {
        /* wait until the transmit data buffer is empty */
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TXE) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        /* send data */
        I2C_SendData(I2Cx, *pucDatas++);
    }

    /* wait until the byte transmission finishes */
    for(timeout = 0; (timeout < (I2C_BYTE_WRITE_TIME_OUT * 2)) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* send a stop condition to I2C bus */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && ((I2Cx->CTLR1 & 0x0200) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    return 0;
}

int8_t cI2CxReadDatas(I2C_TypeDef *I2Cx, uint16_t usIDAddr, uint16_t usRegAddr, void* pvDatas, int32_t iLength)
{
    void (*vI2CxBusReset)(void) = vIIC1DeInit;
    uint8_t *pucDatas = pvDatas;
    uint32_t timeout = 0, startCnt = 0;

    if((iLength < 1) || (pvDatas == NULL))
        return -1;

    /* i2c master sends start signal only when the bus is idle */
    for(timeout = 0; (timeout <= I2C_BUSY_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) != RESET); ++timeout)
    {
        if(timeout >= I2C_BUSY_TIME_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X busy.\r\n", I2Cx);
            return -2;
        }

        vDelayUs(IIC_DELAY_TIME);
    }

    /* 重试 N 次 */
    for(startCnt = 0; startCnt <= I2C_START_OUT; ++startCnt)
    {
        if(startCnt >= I2C_START_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X start out.\r\n", I2Cx);
            return -3;
        }

        I2C_GenerateSTART(I2Cx, ENABLE);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        /* send driver address */
        I2C_Send7bitAddress(I2Cx, usIDAddr, I2C_Direction_Transmitter);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        if(timeout < I2C_BYTE_WRITE_TIME_OUT)
            break;

        vDelayUs(100.0f);
    }

    /* 执行后续操作前，必须清除此状态位 */
    I2C_ClearFlag(I2Cx, I2C_FLAG_ADDR);

    /* send reg address */
    I2C_SendData(I2Cx, usRegAddr);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* 用户手册：必须在START置1前设定 */
    I2Cx->CTLR1 = (iLength == 2) ? (I2Cx->CTLR1 | 0x0800) : (I2Cx->CTLR1 & ~0x0800);

    I2C_GenerateSTART(I2Cx, ENABLE);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* send driver address */
    I2C_Send7bitAddress(I2Cx, usIDAddr, I2C_Direction_Receiver);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* 如果小于3字节，就需要在清除 I2C_FLAG_ADDR 前就设置为NAK */
    I2C_AcknowledgeConfig(I2Cx, (iLength < 3) ? DISABLE : ENABLE);

    /* 清除此bit后，就会立即启动IIC移位寄存器进行数据读取 */
    I2C_ClearFlag(I2Cx, I2C_FLAG_ADDR);

    while((--iLength) > 0)
    {
        /* 等待 BTC bit 置位，以阻止 IIC 在准确设置 ACK/NACK 状态前进行移位 */
        for(timeout = 0; (timeout < (I2C_BYTE_READ_TIME_OUT * 2)) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        I2C_AcknowledgeConfig(I2Cx, (iLength < 3) ? DISABLE : ENABLE);

        /* read data */
        *pucDatas++ = I2C_ReceiveData(I2Cx);
    }

    /* wait until RBNE bit is set */
    for(timeout = 0; (timeout < I2C_BYTE_READ_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* read data */
    *pucDatas++ = I2C_ReceiveData(I2Cx);

    /* send a stop condition to I2C bus */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && ((I2Cx->CTLR1 & 0x0200) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    return 0;
}

/**
 * @brief  设置DMA的数据传输长度，并启动DMA传输
 * @param  DMAy_Channelx：   相应DMA的通道
           Length：          传输长度
 * @retval 无
 */
static void vI2CxDmaAddrAndLenthSet(DMA_Channel_TypeDef *DMAy_Channelx, uint32_t uiMemoryBaseAddr, uint32_t uiPeripheralBaseAddr, uint32_t uiLength)
{
    uint32_t uiDMAyFlag = DMA1_FLAG_GL6, uiTime;

    switch((uint32_t)DMAy_Channelx)
    {
        case (uint32_t)DMA1_Channel6: uiDMAyFlag = DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_HT6 | DMA1_FLAG_TE6; break;
        case (uint32_t)DMA1_Channel7: uiDMAyFlag = DMA1_FLAG_GL7 | DMA1_FLAG_TC7 | DMA1_FLAG_HT7 | DMA1_FLAG_TE7; break;

        default : break;
    }

    /* Disable the peripheral */
    DMAy_Channelx->CFGR &= ~DMA_CFGR1_EN;
    for(uiTime = 1000000; ((RESET != (DMAy_Channelx->CFGR & DMA_CFGR1_EN)) && (uiTime > 0)); --uiTime);

    /* 必须要清除所有中断状态，才允许使能DMA */
    DMA_ClearFlag(uiDMAyFlag);

    /* configure memory base address */
    DMAy_Channelx->MADDR = uiMemoryBaseAddr;

    /* configure peripheral base address */
    DMAy_Channelx->PADDR = uiPeripheralBaseAddr;

    /* Configure DMA Stream data length */
    DMAy_Channelx->CNTR = uiLength;

    /* Enable the Peripheral */
    DMAy_Channelx->CFGR |= DMA_CFGR1_EN;
    for(uiTime = 1000000; ((RESET == (DMAy_Channelx->CFGR & DMA_CFGR1_EN)) && (uiTime > 0)); --uiTime);
}

int8_t cI2CxDmaWriteDatas(I2C_TypeDef *I2Cx, uint16_t usIDAddr, uint16_t usRegAddr, void* pvDatas, int32_t iLength)
{
    void (*vI2CxBusReset)(void) = vIIC1DeInit;
    uint32_t timeout = 0, startCnt = 0;

    if((iLength < 1) || (pvDatas == NULL))
        return -1;

    /* i2c master sends start signal only when the bus is idle */
    for(timeout = 0; (timeout <= I2C_BUSY_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) != RESET); ++timeout)
    {
        if(timeout >= I2C_BUSY_TIME_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X busy.\r\n", I2Cx);
            return -2;
        }

        vDelayUs(IIC_DELAY_TIME);
    }

    /* 重试 N 次 */
    for(startCnt = 0; startCnt <= I2C_START_OUT; ++startCnt)
    {
        if(startCnt >= I2C_START_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X start out.\r\n", I2Cx);
            return -3;
        }

        I2C_GenerateSTART(I2Cx, ENABLE);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        /* send driver address */
        I2C_Send7bitAddress(I2Cx, usIDAddr, I2C_Direction_Transmitter);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        if(timeout < I2C_BYTE_WRITE_TIME_OUT)
            break;

        vDelayUs(100.0f);
    }

    /* 执行后续操作前，必须清除此状态位 */
    I2C_ClearFlag(I2Cx, I2C_FLAG_ADDR);

    /* send reg address */
    I2C_SendData(I2Cx, usRegAddr);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* 设置传输地址与长度，并启动DMA发送 */
    vI2CxDmaAddrAndLenthSet(DMA1_Channel6, (uint32_t)pvDatas, (uint32_t)(&I2Cx->DATAR), iLength);

    /* 在此放大20倍，是为了在以下超时检测时，减少延时周期，以能够在满足条件时快速退出等待 */
    iLength *= 20;

    /* 等待本次DMA传输完成 */
    while((DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET)   &&
          (DMA1_Channel6->CFGR & DMA_CFGR1_EN)          &&
          (DMA1_Channel6->CNTR > 0)                     &&
          ((iLength--) > 0))
    {
        /* 以10k波特率计算时长（1Byte + 1bit ACK/NACK = 9bit；除以20，是因为上面放大了20倍） */
        vDelayUs(IIC_DELAY_TIME * 9.0f / 20.0f + 1.0f);
    }

    /* wait until the byte transmission finishes */
    for(timeout = 0; (timeout < (I2C_BYTE_WRITE_TIME_OUT * 2)) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* send a stop condition to I2C bus */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && ((I2Cx->CTLR1 & 0x0200) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    return 0;
}

int8_t cI2CxDmaReadDatas(I2C_TypeDef *I2Cx, uint16_t usIDAddr, uint16_t usRegAddr, void* pvDatas, int32_t iLength)
{
    void (*vI2CxBusReset)(void) = vIIC1DeInit;
    uint32_t timeout = 0, startCnt = 0;

    if((iLength < 1) || (pvDatas == NULL))
        return -1;

    /* i2c master sends start signal only when the bus is idle */
    for(timeout = 0; (timeout <= I2C_BUSY_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) != RESET); ++timeout)
    {
        if(timeout >= I2C_BUSY_TIME_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X busy.\r\n", I2Cx);
            return -2;
        }

        vDelayUs(IIC_DELAY_TIME);
    }

    /* 重试 N 次 */
    for(startCnt = 0; startCnt <= I2C_START_OUT; ++startCnt)
    {
        if(startCnt >= I2C_START_OUT)
        {
            vI2CxBusReset();
//            printf("cI2C %08X start out.\r\n", I2Cx);
            return -3;
        }

        I2C_GenerateSTART(I2Cx, ENABLE);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        /* send driver address */
        I2C_Send7bitAddress(I2Cx, usIDAddr, I2C_Direction_Transmitter);
        for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET); ++timeout)
            vDelayUs(IIC_DELAY_TIME);

        if(timeout < I2C_BYTE_WRITE_TIME_OUT)
            break;

        vDelayUs(100.0f);
    }

    I2C_ClearFlag(I2Cx, I2C_FLAG_ADDR);

    /* send reg address */
    I2C_SendData(I2Cx, usRegAddr);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* 用户手册：必须在START置1前设定 */
    I2Cx->CTLR1 &= ~0x0800;

    I2C_GenerateSTART(I2Cx, ENABLE);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* send driver address */
    I2C_Send7bitAddress(I2Cx, usIDAddr, I2C_Direction_Receiver);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    /* 如果等于1字节，就需要在清除 I2C_FLAG_ADDR 前就设置为NAK */
    I2C_AcknowledgeConfig(I2Cx, (iLength == 1) ? DISABLE : ENABLE);

    /* 设置DMA传输结束后，发送NACK */
    I2C_DMALastTransferCmd(I2Cx, ENABLE);

    /* 设置传输地址与长度，并启动DMA发送 */
    vI2CxDmaAddrAndLenthSet(DMA1_Channel7, (uint32_t)pvDatas, (uint32_t)(&I2Cx->DATAR), iLength);

    /* 清除此bit后，就会立即启动IIC移位寄存器进行数据读取 */
    I2C_ClearFlag(I2Cx, I2C_FLAG_ADDR);

    /* 在此放大20倍，是为了在以下超时检测时，减少延时周期，以能够在满足条件时快速退出等待 */
    iLength *= 20;

    /* 等待本次DMA传输完成 */
    while((DMA_GetFlagStatus(DMA1_FLAG_TC7) == RESET)   &&
          (DMA1_Channel7->CFGR & DMA_CFGR1_EN)          &&
          (DMA1_Channel7->CNTR > 0)                     &&
          ((iLength--) > 0))
    {
        /* 以10k波特率计算时长（1Byte + 1bit ACK/NACK = 9bit；除以20，是因为上面放大了20倍） */
        vDelayUs(IIC_DELAY_TIME * 9.0f / 20.0f + 1.0f);
    }

    /* send a stop condition to I2C bus */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    for(timeout = 0; (timeout < I2C_BYTE_WRITE_TIME_OUT) && ((I2Cx->CTLR1 & 0x0200) == RESET); ++timeout)
        vDelayUs(IIC_DELAY_TIME);

    return 0;
}
